home *** CD-ROM | disk | FTP | other *** search
/ Amiga Format CD 24 / Amiga Format AFCD24 (Feb 1998, Issue 108).iso / -in_the_mag- / emulation / amiga / uae-0.7.0b2 / src / fpp.c < prev    next >
C/C++ Source or Header  |  1998-01-20  |  30KB  |  1,345 lines

  1.  /*
  2.   * UAE - The Un*x Amiga Emulator
  3.   *
  4.   * MC68881 emulation
  5.   *
  6.   * Copyright 1996 Herman ten Brugge
  7.   */
  8.  
  9. #include <math.h>
  10.  
  11. #include "sysconfig.h"
  12. #include "sysdeps.h"
  13.  
  14. #include "config.h"
  15. #include "options.h"
  16. #include "memory.h"
  17. #include "custom.h"
  18. #include "readcpu.h"
  19. #include "newcpu.h"
  20. #include "ersatz.h"
  21.  
  22. #if CPU_LEVEL >= 3
  23.  
  24. #define    DEBUG_FPP    0
  25.  
  26. /* single   : S  8*E 23*F */
  27. /* double   : S 11*E 52*F */
  28. /* extended : S 15*E 64*F */
  29. /* E = 0 & F = 0 -> 0 */
  30. /* E = MAX & F = 0 -> Infin */
  31. /* E = MAX & F # 0 -> NotANumber */
  32. /* E = biased by 127 (single) ,1023 (double) ,16383 (extended) */
  33.  
  34. static __inline__ double to_single(uae_u32 value)
  35. {
  36.     double frac;
  37.  
  38.     if ((value & 0x7fffffff) == 0)
  39.     return (0.0);
  40.     frac = (double) ((value & 0x7fffff) | 0x800000) / 8388608.0;
  41.     if (value & 0x80000000)
  42.     frac = -frac;
  43.     return (ldexp(frac, ((value >> 23) & 0xff) - 127));
  44. }
  45.  
  46. static __inline__ uae_u32
  47.  from_single(double src)
  48. {
  49.     int expon;
  50.     uae_u32 tmp;
  51.     double frac;
  52.  
  53.     if (src == 0.0)
  54.     return 0;
  55.     if (src < 0) {
  56.     tmp = 0x80000000;
  57.     src = -src;
  58.     } else {
  59.     tmp = 0;
  60.     }
  61.     frac = frexp(src, &expon);
  62.     frac += 0.5 / 16777216.0;
  63.     if (frac >= 1.0) {
  64.     frac /= 2.0;
  65.     expon++;
  66.     }
  67.     return (tmp | (((expon + 127 - 1) & 0xff) << 23) |
  68.         (((int) (frac * 16777216.0)) & 0x7fffff));
  69. }
  70.  
  71. static __inline__ double to_exten(uae_u32 wrd1, uae_u32 wrd2, uae_u32 wrd3)
  72. {
  73.     double frac;
  74.  
  75.     if ((wrd1 & 0x7fff0000) == 0 && wrd2 == 0 && wrd3 == 0)
  76.     return 0.0;
  77.     frac = (double) wrd2 / 2147483648.0 +
  78.     (double) wrd3 / 9223372036854775808.0;
  79.     if (wrd1 & 0x80000000)
  80.     frac = -frac;
  81.     return ldexp(frac, ((wrd1 >> 16) & 0x7fff) - 16383);
  82. }
  83.  
  84. static __inline__ void from_exten(double src, uae_u32 * wrd1, uae_u32 * wrd2, uae_u32 * wrd3)
  85. {
  86.     int expon;
  87.     double frac;
  88.  
  89.     if (src == 0.0) {
  90.     *wrd1 = 0;
  91.     *wrd2 = 0;
  92.     *wrd3 = 0;
  93.     return;
  94.     }
  95.     if (src < 0) {
  96.     *wrd1 = 0x80000000;
  97.     src = -src;
  98.     } else {
  99.     *wrd1 = 0;
  100.     }
  101.     frac = frexp(src, &expon);
  102.     frac += 0.5 / 18446744073709551616.0;
  103.     if (frac >= 1.0) {
  104.     frac /= 2.0;
  105.     expon++;
  106.     }
  107.     *wrd1 |= (((expon + 16383 - 1) & 0x7fff) << 16);
  108.     *wrd2 = (uae_u32) (frac * 4294967296.0);
  109.     *wrd3 = (uae_u32) (frac * 18446744073709551616.0 - *wrd2 * 4294967296.0);
  110. }
  111.  
  112. static __inline__ double to_double(uae_u32 wrd1, uae_u32 wrd2)
  113. {
  114.     double frac;
  115.  
  116.     if ((wrd1 & 0x7fffffff) == 0 && wrd2 == 0)
  117.     return 0.0;
  118.     frac = (double) ((wrd1 & 0xfffff) | 0x100000) / 1048576.0 +
  119.     (double) wrd2 / 4503599627370496.0;
  120.     if (wrd1 & 0x80000000)
  121.     frac = -frac;
  122.     return ldexp(frac, ((wrd1 >> 20) & 0x7ff) - 1023);
  123. }
  124.  
  125. static __inline__ void from_double(double src, uae_u32 * wrd1, uae_u32 * wrd2)
  126. {
  127.     int expon;
  128.     int tmp;
  129.     double frac;
  130.  
  131.     if (src == 0.0) {
  132.     *wrd1 = 0;
  133.     *wrd2 = 0;
  134.     return;
  135.     }
  136.     if (src < 0) {
  137.     *wrd1 = 0x80000000;
  138.     src = -src;
  139.     } else {
  140.     *wrd1 = 0;
  141.     }
  142.     frac = frexp(src, &expon);
  143.     frac += 0.5 / 9007199254740992.0;
  144.     if (frac >= 1.0) {
  145.     frac /= 2.0;
  146.     expon++;
  147.     }
  148.     tmp = (uae_u32) (frac * 2097152.0);
  149.     *wrd1 |= (((expon + 1023 - 1) & 0x7ff) << 20) | (tmp & 0xfffff);
  150.     *wrd2 = (uae_u32) (frac * 9007199254740992.0 - tmp * 4294967296.0);
  151. }
  152.  
  153. static __inline__ double to_pack(uae_u32 wrd1, uae_u32 wrd2, uae_u32 wrd3)
  154. {
  155.     double d;
  156.     char *cp;
  157.     char str[100];
  158.  
  159.     cp = str;
  160.     if (wrd1 & 0x80000000)
  161.     *cp++ = '-';
  162.     *cp++ = (wrd1 & 0xf) + '0';
  163.     *cp++ = '.';
  164.     *cp++ = ((wrd2 >> 28) & 0xf) + '0';
  165.     *cp++ = ((wrd2 >> 24) & 0xf) + '0';
  166.     *cp++ = ((wrd2 >> 20) & 0xf) + '0';
  167.     *cp++ = ((wrd2 >> 16) & 0xf) + '0';
  168.     *cp++ = ((wrd2 >> 12) & 0xf) + '0';
  169.     *cp++ = ((wrd2 >> 8) & 0xf) + '0';
  170.     *cp++ = ((wrd2 >> 4) & 0xf) + '0';
  171.     *cp++ = ((wrd2 >> 0) & 0xf) + '0';
  172.     *cp++ = ((wrd3 >> 28) & 0xf) + '0';
  173.     *cp++ = ((wrd3 >> 24) & 0xf) + '0';
  174.     *cp++ = ((wrd3 >> 20) & 0xf) + '0';
  175.     *cp++ = ((wrd3 >> 16) & 0xf) + '0';
  176.     *cp++ = ((wrd3 >> 12) & 0xf) + '0';
  177.     *cp++ = ((wrd3 >> 8) & 0xf) + '0';
  178.     *cp++ = ((wrd3 >> 4) & 0xf) + '0';
  179.     *cp++ = ((wrd3 >> 0) & 0xf) + '0';
  180.     *cp++ = 'E';
  181.     if (wrd1 & 0x40000000)
  182.     *cp++ = '-';
  183.     *cp++ = ((wrd1 >> 24) & 0xf) + '0';
  184.     *cp++ = ((wrd1 >> 20) & 0xf) + '0';
  185.     *cp++ = ((wrd1 >> 16) & 0xf) + '0';
  186.     *cp = 0;
  187.     sscanf(str, "%le", &d);
  188.     return d;
  189. }
  190.  
  191. static __inline__ void from_pack(double src, uae_u32 * wrd1, uae_u32 * wrd2, uae_u32 * wrd3)
  192. {
  193.     int i;
  194.     int t;
  195.     char *cp;
  196.     char str[100];
  197.  
  198.     sprintf(str, "%.16e", src);
  199.     cp = str;
  200.     *wrd1 = *wrd2 = *wrd3 = 0;
  201.     if (*cp == '-') {
  202.     cp++;
  203.     *wrd1 = 0x80000000;
  204.     }
  205.     if (*cp == '+')
  206.     cp++;
  207.     *wrd1 |= (*cp++ - '0');
  208.     if (*cp == '.')
  209.     cp++;
  210.     for (i = 0; i < 8; i++) {
  211.     *wrd2 <<= 4;
  212.     if (*cp >= '0' && *cp <= '9')
  213.         *wrd2 |= *cp++ - '0';
  214.     }
  215.     for (i = 0; i < 8; i++) {
  216.     *wrd3 <<= 4;
  217.     if (*cp >= '0' && *cp <= '9')
  218.         *wrd3 |= *cp++ - '0';
  219.     }
  220.     if (*cp == 'e' || *cp == 'E') {
  221.     cp++;
  222.     if (*cp == '-') {
  223.         cp++;
  224.         *wrd1 |= 0x40000000;
  225.     }
  226.     if (*cp == '+')
  227.         cp++;
  228.     t = 0;
  229.     for (i = 0; i < 3; i++) {
  230.         if (*cp >= '0' && *cp <= '9')
  231.         t = (t << 4) | (*cp++ - '0');
  232.     }
  233.     *wrd1 |= t << 16;
  234.     }
  235. }
  236.  
  237. static __inline__ int get_fp_value(uae_u32 opcode, uae_u16 extra, double *src)
  238. {
  239.     uaecptr tmppc;
  240.     uae_u16 tmp;
  241.     int size;
  242.     int mode;
  243.     int reg;
  244.     uae_u32 ad = 0;
  245.     static int sz1[8] =
  246.     {4, 4, 12, 12, 2, 8, 1, 0};
  247.     static int sz2[8] =
  248.     {4, 4, 12, 12, 2, 8, 2, 0};
  249.  
  250.     if ((extra & 0x4000) == 0) {
  251.     *src = regs.fp[(extra >> 10) & 7];
  252.     return 1;
  253.     }
  254.     mode = (opcode >> 3) & 7;
  255.     reg = opcode & 7;
  256.     size = (extra >> 10) & 7;
  257.     switch (mode) {
  258.     case 0:
  259.     switch (size) {
  260.     case 6:
  261.         *src = (double) (uae_s8) m68k_dreg(regs, reg);
  262.         break;
  263.     case 4:
  264.         *src = (double) (uae_s16) m68k_dreg(regs, reg);
  265.         break;
  266.     case 0:
  267.         *src = (double) (uae_s32) m68k_dreg(regs, reg);
  268.         break;
  269.     case 1:
  270.         *src = to_single(m68k_dreg(regs, reg));
  271.         break;
  272.     default:
  273.         return 0;
  274.     }
  275.     return 1;
  276.     case 1:
  277.     return 0;
  278.     case 2:
  279.     ad = m68k_areg(regs, reg);
  280.     break;
  281.     case 3:
  282.     ad = m68k_areg(regs, reg);
  283.     m68k_areg(regs, reg) += reg == 7 ? sz2[size] : sz1[size];
  284.     break;
  285.     case 4:
  286.     m68k_areg(regs, reg) -= reg == 7 ? sz2[size] : sz1[size];
  287.     ad = m68k_areg(regs, reg);
  288.     break;
  289.     case 5:
  290.     ad = m68k_areg(regs, reg) + (uae_s32) (uae_s16) nextiword();
  291.     break;
  292.     case 6:
  293.     ad = get_disp_ea(m68k_areg(regs, reg), nextiword());
  294.     break;
  295.     case 7:
  296.     switch (reg) {
  297.     case 0:
  298.         ad = (uae_s32) (uae_s16) nextiword();
  299.         break;
  300.     case 1:
  301.         ad = nextilong();
  302.         break;
  303.     case 2:
  304.         ad = m68k_getpc();
  305.         ad += (uae_s32) (uae_s16) nextiword();
  306.         break;
  307.     case 3:
  308.         tmppc = m68k_getpc();
  309.         tmp = nextiword();
  310.         ad = get_disp_ea(tmppc, tmp);
  311.         break;
  312.     case 4:
  313.         ad = m68k_getpc();
  314.         m68k_setpc(ad + sz2[size]);
  315.         break;
  316.     default:
  317.         return 0;
  318.     }
  319.     }
  320.     switch (size) {
  321.     case 0:
  322.     *src = (double) (uae_s32) get_long(ad);
  323.     break;
  324.     case 1:
  325.     *src = to_single(get_long(ad));
  326.     break;
  327.     case 2:{
  328.         uae_u32 wrd1, wrd2, wrd3;
  329.         wrd1 = get_long(ad);
  330.         ad += 4;
  331.         wrd2 = get_long(ad);
  332.         ad += 4;
  333.         wrd3 = get_long(ad);
  334.         *src = to_exten(wrd1, wrd2, wrd3);
  335.     }
  336.     break;
  337.     case 3:{
  338.         uae_u32 wrd1, wrd2, wrd3;
  339.         wrd1 = get_long(ad);
  340.         ad += 4;
  341.         wrd2 = get_long(ad);
  342.         ad += 4;
  343.         wrd3 = get_long(ad);
  344.         *src = to_pack(wrd1, wrd2, wrd3);
  345.     }
  346.     break;
  347.     case 4:
  348.     *src = (double) (uae_s16) get_word(ad);
  349.     break;
  350.     case 5:{
  351.         uae_u32 wrd1, wrd2;
  352.         wrd1 = get_long(ad);
  353.         ad += 4;
  354.         wrd2 = get_long(ad);
  355.         *src = to_double(wrd1, wrd2);
  356.     }
  357.     break;
  358.     case 6:
  359.     *src = (double) (uae_s8) get_byte(ad);
  360.     break;
  361.     default:
  362.     return 0;
  363.     }
  364.     return 1;
  365. }
  366.  
  367. static __inline__ int put_fp_value(double value, uae_u32 opcode, uae_u16 extra)
  368. {
  369.     uae_u16 tmp;
  370.     uaecptr tmppc;
  371.     int size;
  372.     int mode;
  373.     int reg;
  374.     uae_u32 ad;
  375.     static int sz1[8] =
  376.     {4, 4, 12, 12, 2, 8, 1, 0};
  377.     static int sz2[8] =
  378.     {4, 4, 12, 12, 2, 8, 2, 0};
  379.  
  380.     if ((extra & 0x4000) == 0) {
  381.     regs.fp[(extra >> 10) & 7] = value;
  382.     return 1;
  383.     }
  384.     mode = (opcode >> 3) & 7;
  385.     reg = opcode & 7;
  386.     size = (extra >> 10) & 7;
  387.     ad = -1;
  388.     switch (mode) {
  389.     case 0:
  390.     switch (size) {
  391.     case 6:
  392.         m68k_dreg(regs, reg) = (((int) value & 0xff)
  393.                     | (m68k_dreg(regs, reg) & ~0xff));
  394.         break;
  395.     case 4:
  396.         m68k_dreg(regs, reg) = (((int) value & 0xffff)
  397.                     | (m68k_dreg(regs, reg) & ~0xffff));
  398.         break;
  399.     case 0:
  400.         m68k_dreg(regs, reg) = (int) value;
  401.         break;
  402.     case 1:
  403.         m68k_dreg(regs, reg) = from_single(value);
  404.         break;
  405.     default:
  406.         return 0;
  407.     }
  408.     return 1;
  409.     case 1:
  410.     return 0;
  411.     case 2:
  412.     ad = m68k_areg(regs, reg);
  413.     break;
  414.     case 3:
  415.     ad = m68k_areg(regs, reg);
  416.     m68k_areg(regs, reg) += reg == 7 ? sz2[size] : sz1[size];
  417.     break;
  418.     case 4:
  419.     m68k_areg(regs, reg) -= reg == 7 ? sz2[size] : sz1[size];
  420.     ad = m68k_areg(regs, reg);
  421.     break;
  422.     case 5:
  423.     ad = m68k_areg(regs, reg) + (uae_s32) (uae_s16) nextiword();
  424.     break;
  425.     case 6:
  426.     ad = get_disp_ea(m68k_areg(regs, reg), nextiword());
  427.     break;
  428.     case 7:
  429.     switch (reg) {
  430.     case 0:
  431.         ad = (uae_s32) (uae_s16) nextiword();
  432.         break;
  433.     case 1:
  434.         ad = nextilong();
  435.         break;
  436.     case 2:
  437.         ad = m68k_getpc();
  438.         ad += (uae_s32) (uae_s16) nextiword();
  439.         break;
  440.     case 3:
  441.         tmppc = m68k_getpc();
  442.         tmp = nextiword();
  443.         ad = get_disp_ea(tmppc, tmp);
  444.         break;
  445.     case 4:
  446.         ad = m68k_getpc();
  447.         m68k_setpc(ad + sz2[size]);
  448.         break;
  449.     default:
  450.         return 0;
  451.     }
  452.     }
  453.     switch (size) {
  454.     case 0:
  455.     put_long(ad, (uae_s32) value);
  456.     break;
  457.     case 1:
  458.     put_long(ad, from_single(value));
  459.     break;
  460.     case 2:
  461.     {
  462.         uae_u32 wrd1, wrd2, wrd3;
  463.         from_exten(value, &wrd1, &wrd2, &wrd3);
  464.         put_long(ad, wrd1);
  465.         ad += 4;
  466.         put_long(ad, wrd2);
  467.         ad += 4;
  468.         put_long(ad, wrd3);
  469.     }
  470.     break;
  471.     case 3:
  472.     {
  473.         uae_u32 wrd1, wrd2, wrd3;
  474.         from_pack(value, &wrd1, &wrd2, &wrd3);
  475.         put_long(ad, wrd1);
  476.         ad += 4;
  477.         put_long(ad, wrd2);
  478.         ad += 4;
  479.         put_long(ad, wrd3);
  480.     }
  481.     break;
  482.     case 4:
  483.     put_word(ad, (uae_s16) value);
  484.     break;
  485.     case 5:{
  486.         uae_u32 wrd1, wrd2;
  487.         from_double(value, &wrd1, &wrd2);
  488.         put_long(ad, wrd1);
  489.         ad += 4;
  490.         put_long(ad, wrd2);
  491.     }
  492.     break;
  493.     case 6:
  494.     put_byte(ad, (uae_s8) value);
  495.     break;
  496.     default:
  497.     return 0;
  498.     }
  499.     return 1;
  500. }
  501.  
  502. static __inline__ int get_fp_ad(uae_u32 opcode, uae_u32 * ad)
  503. {
  504.     uae_u16 tmp;
  505.     uaecptr tmppc;
  506.     int mode;
  507.     int reg;
  508.  
  509.     mode = (opcode >> 3) & 7;
  510.     reg = opcode & 7;
  511.     switch (mode) {
  512.     case 0:
  513.     case 1:
  514.     return 0;
  515.     case 2:
  516.     *ad = m68k_areg(regs, reg);
  517.     break;
  518.     case 3:
  519.     *ad = m68k_areg(regs, reg);
  520.     break;
  521.     case 4:
  522.     *ad = m68k_areg(regs, reg);
  523.     break;
  524.     case 5:
  525.     *ad = m68k_areg(regs, reg) + (uae_s32) (uae_s16) nextiword();
  526.     break;
  527.     case 6:
  528.     *ad = get_disp_ea(m68k_areg(regs, reg), nextiword());
  529.     break;
  530.     case 7:
  531.     switch (reg) {
  532.     case 0:
  533.         *ad = (uae_s32) (uae_s16) nextiword();
  534.         break;
  535.     case 1:
  536.         *ad = nextilong();
  537.         break;
  538.     case 2:
  539.         *ad = m68k_getpc();
  540.         *ad += (uae_s32) (uae_s16) nextiword();
  541.         break;
  542.     case 3:
  543.         tmppc = m68k_getpc();
  544.         tmp = nextiword();
  545.         *ad = get_disp_ea(tmppc, tmp);
  546.         break;
  547.     default:
  548.         return 0;
  549.     }
  550.     }
  551.     return 1;
  552. }
  553.  
  554. static __inline__ int fpp_cond(uae_u32 opcode, int contition)
  555. {
  556.     int N = (regs.fpsr & 0x8000000) != 0;
  557.     int Z = (regs.fpsr & 0x4000000) != 0;
  558.     /* int I = (regs.fpsr & 0x2000000) != 0; */
  559.     int NotANumber = (regs.fpsr & 0x1000000) != 0;
  560.  
  561.     switch (contition) {
  562.     case 0x00:
  563.     return 0;
  564.     case 0x01:
  565.     return Z;
  566.     case 0x02:
  567.     return !(NotANumber || Z || N);
  568.     case 0x03:
  569.     return Z || !(NotANumber || N);
  570.     case 0x04:
  571.     return N && !(NotANumber || Z);
  572.     case 0x05:
  573.     return Z || (N && !NotANumber);
  574.     case 0x06:
  575.     return !(NotANumber || Z);
  576.     case 0x07:
  577.     return !NotANumber;
  578.     case 0x08:
  579.     return NotANumber;
  580.     case 0x09:
  581.     return NotANumber || Z;
  582.     case 0x0a:
  583.     return NotANumber || !(N || Z);
  584.     case 0x0b:
  585.     return NotANumber || Z || !N;
  586.     case 0x0c:
  587.     return NotANumber || (N && !Z);
  588.     case 0x0d:
  589.     return NotANumber || Z || N;
  590.     case 0x0e:
  591.     return !Z;
  592.     case 0x0f:
  593.     return 1;
  594.     case 0x10:
  595.     return 0;
  596.     case 0x11:
  597.     return Z;
  598.     case 0x12:
  599.     return !(NotANumber || Z || N);
  600.     case 0x13:
  601.     return Z || !(NotANumber || N);
  602.     case 0x14:
  603.     return N && !(NotANumber || Z);
  604.     case 0x15:
  605.     return Z || (N && !NotANumber);
  606.     case 0x16:
  607.     return !(NotANumber || Z);
  608.     case 0x17:
  609.     return !NotANumber;
  610.     case 0x18:
  611.     return NotANumber;
  612.     case 0x19:
  613.     return NotANumber || Z;
  614.     case 0x1a:
  615.     return NotANumber || !(N || Z);
  616.     case 0x1b:
  617.     return NotANumber || Z || !N;
  618.     case 0x1c:
  619.     return NotANumber || (Z && N);
  620.     case 0x1d:
  621.     return NotANumber || Z || N;
  622.     case 0x1e:
  623.     return !Z;
  624.     case 0x1f:
  625.     return 1;
  626.     }
  627.     return -1;
  628. }
  629.  
  630. void fdbcc_opp(uae_u32 opcode, uae_u16 extra)
  631. {
  632.     uaecptr pc = (uae_u32) m68k_getpc();
  633.     uae_s32 disp = (uae_s32) (uae_s16) nextiword();
  634.     int cc;
  635.  
  636. #if DEBUG_FPP
  637.     printf("fdbcc_opp at %08lx\n", m68k_getpc());
  638.     fflush(stdout);
  639. #endif
  640.     cc = fpp_cond(opcode, extra & 0x3f);
  641.     if (cc == -1) {
  642.     m68k_setpc(pc - 4);
  643.     op_illg(opcode);
  644.     } else if (!cc) {
  645.     int reg = opcode & 0x7;
  646.  
  647.     m68k_dreg(regs, reg) = ((m68k_dreg(regs, reg) & ~0xffff)
  648.                 | ((m68k_dreg(regs, reg) - 1) & 0xffff));
  649.     if ((m68k_dreg(regs, reg) & 0xffff) == 0xffff)
  650.         m68k_setpc(pc + disp);
  651.     }
  652. }
  653.  
  654. void fscc_opp(uae_u32 opcode, uae_u16 extra)
  655. {
  656.     uae_u32 ad;
  657.     int cc;
  658.  
  659. #if DEBUG_FPP
  660.     printf("fscc_opp at %08lx\n", m68k_getpc());
  661.     fflush(stdout);
  662. #endif
  663.     cc = fpp_cond(opcode, extra & 0x3f);
  664.     if (cc == -1) {
  665.     m68k_setpc(m68k_getpc() - 4);
  666.     op_illg(opcode);
  667.     } else if ((opcode & 0x38) == 0) {
  668.     m68k_dreg(regs, opcode & 7) = (m68k_dreg(regs, opcode & 7) & ~0xff) |
  669.         (cc ? 0xff : 0x00);
  670.     } else {
  671.     if (get_fp_ad(opcode, &ad) == 0) {
  672.         m68k_setpc(m68k_getpc() - 4);
  673.         op_illg(opcode);
  674.     } else
  675.         put_byte(ad, cc ? 0xff : 0x00);
  676.     }
  677. }
  678.  
  679. void ftrapcc_opp(uae_u32 opcode, uaecptr oldpc)
  680. {
  681.     int cc;
  682.  
  683. #if DEBUG_FPP
  684.     printf("ftrapcc_opp at %08lx\n", m68k_getpc());
  685.     fflush(stdout);
  686. #endif
  687.     cc = fpp_cond(opcode, opcode & 0x3f);
  688.     if (cc == -1) {
  689.     m68k_setpc(oldpc);
  690.     op_illg(opcode);
  691.     }
  692.     if (cc)
  693.     Exception(7, oldpc - 2);
  694. }
  695.  
  696. void fbcc_opp(uae_u32 opcode, uaecptr pc, uae_u32 extra)
  697. {
  698.     int cc;
  699.  
  700. #if DEBUG_FPP
  701.     printf("fbcc_opp at %08lx\n", m68k_getpc());
  702.     fflush(stdout);
  703. #endif
  704.     cc = fpp_cond(opcode, opcode & 0x3f);
  705.     if (cc == -1) {
  706.     m68k_setpc(pc);
  707.     op_illg(opcode);
  708.     } else if (cc) {
  709.     if ((opcode & 0x40) == 0)
  710.         extra = (uae_s32) (uae_s16) extra;
  711.     m68k_setpc(pc + extra);
  712.     }
  713. }
  714.  
  715. void fsave_opp(uae_u32 opcode)
  716. {
  717.     uae_u32 ad;
  718.     int incr = (opcode & 0x38) == 0x20 ? -1 : 1;
  719.     int i;
  720.  
  721. #if DEBUG_FPP
  722.     printf("fsave_opp at %08lx\n", m68k_getpc());
  723.     fflush(stdout);
  724. #endif
  725.     if (get_fp_ad(opcode, &ad) == 0) {
  726.     m68k_setpc (m68k_getpc () - 2);
  727.     op_illg(opcode);
  728.     return;
  729.     }
  730.     if (incr < 0) {
  731.     ad -= 4;
  732.     put_long(ad, 0x70000000);
  733.     for (i = 0; i < 5; i++) {
  734.         ad -= 4;
  735.         put_long(ad, 0x00000000);
  736.     }
  737.     ad -= 4;
  738.     put_long(ad, 0x1f180000);
  739.     } else {
  740.     put_long(ad, 0x1f180000);
  741.     ad += 4;
  742.     for (i = 0; i < 5; i++) {
  743.         put_long(ad, 0x00000000);
  744.         ad += 4;
  745.     }
  746.     put_long(ad, 0x70000000);
  747.     ad += 4;
  748.     }
  749.     if ((opcode & 0x38) == 0x18)
  750.     m68k_areg(regs, opcode & 7) = ad;
  751.     if ((opcode & 0x38) == 0x20)
  752.     m68k_areg(regs, opcode & 7) = ad;
  753. }
  754.  
  755. void frestore_opp(uae_u32 opcode)
  756. {
  757.     uae_u32 ad;
  758.     uae_u32 d;
  759.     int incr = (opcode & 0x38) == 0x20 ? -1 : 1;
  760.  
  761. #if DEBUG_FPP
  762.     printf("frestore_opp at %08lx\n", m68k_getpc());
  763.     fflush(stdout);
  764. #endif
  765.     if (get_fp_ad(opcode, &ad) == 0) {
  766.     m68k_setpc (m68k_getpc () - 2);
  767.     op_illg(opcode);
  768.     return;
  769.     }
  770.     if (incr < 0) {
  771.     ad -= 4;
  772.     d = get_long(ad);
  773.     if ((d & 0xff000000) != 0) {
  774.         if ((d & 0x00ff0000) == 0x00180000)
  775.         ad -= 6 * 4;
  776.         else if ((d & 0x00ff0000) == 0x00380000)
  777.         ad -= 14 * 4;
  778.         else if ((d & 0x00ff0000) == 0x00b40000)
  779.         ad -= 45 * 4;
  780.     }
  781.     } else {
  782.     d = get_long(ad);
  783.     ad += 4;
  784.     if ((d & 0xff000000) != 0) {
  785.         if ((d & 0x00ff0000) == 0x00180000)
  786.         ad += 6 * 4;
  787.         else if ((d & 0x00ff0000) == 0x00380000)
  788.         ad += 14 * 4;
  789.         else if ((d & 0x00ff0000) == 0x00b40000)
  790.         ad += 45 * 4;
  791.     }
  792.     }
  793.     if ((opcode & 0x38) == 0x18)
  794.     m68k_areg(regs, opcode & 7) = ad;
  795.     if ((opcode & 0x38) == 0x20)
  796.     m68k_areg(regs, opcode & 7) = ad;
  797. }
  798.  
  799. void fpp_opp(uae_u32 opcode, uae_u16 extra)
  800. {
  801.     int reg;
  802.     double src;
  803.  
  804. #if DEBUG_FPP
  805.     printf("FPP %04lx %04x at %08lx\n", opcode & 0xffff, extra & 0xffff,
  806.        m68k_getpc() - 4);
  807.     fflush(stdout);
  808. #endif
  809.     switch ((extra >> 13) & 0x7) {
  810.     case 3:
  811.     if (put_fp_value(regs.fp[(extra >> 7) & 7], opcode, extra) == 0) {
  812.         m68k_setpc(m68k_getpc() - 4);
  813.         op_illg(opcode);
  814.     }
  815.     return;
  816.     case 4:
  817.     case 5:
  818.     if ((opcode & 0x38) == 0) {
  819.         if (extra & 0x2000) {
  820.         if (extra & 0x1000)
  821.             m68k_dreg(regs, opcode & 7) = regs.fpcr;
  822.         if (extra & 0x0800)
  823.             m68k_dreg(regs, opcode & 7) = regs.fpsr;
  824.         if (extra & 0x0400)
  825.             m68k_dreg(regs, opcode & 7) = regs.fpiar;
  826.         } else {
  827.         if (extra & 0x1000)
  828.             regs.fpcr = m68k_dreg(regs, opcode & 7);
  829.         if (extra & 0x0800)
  830.             regs.fpsr = m68k_dreg(regs, opcode & 7);
  831.         if (extra & 0x0400)
  832.             regs.fpiar = m68k_dreg(regs, opcode & 7);
  833.         }
  834.     } else if ((opcode & 0x38) == 1) {
  835.         if (extra & 0x2000) {
  836.         if (extra & 0x1000)
  837.             m68k_areg(regs, opcode & 7) = regs.fpcr;
  838.         if (extra & 0x0800)
  839.             m68k_areg(regs, opcode & 7) = regs.fpsr;
  840.         if (extra & 0x0400)
  841.             m68k_areg(regs, opcode & 7) = regs.fpiar;
  842.         } else {
  843.         if (extra & 0x1000)
  844.             regs.fpcr = m68k_areg(regs, opcode & 7);
  845.         if (extra & 0x0800)
  846.             regs.fpsr = m68k_areg(regs, opcode & 7);
  847.         if (extra & 0x0400)
  848.             regs.fpiar = m68k_areg(regs, opcode & 7);
  849.         }
  850.     } else if ((opcode & 0x3f) == 0x3c) {
  851.         if ((extra & 0x2000) == 0) {
  852.         if (extra & 0x1000)
  853.             regs.fpcr = nextilong();
  854.         if (extra & 0x0800)
  855.             regs.fpsr = nextilong();
  856.         if (extra & 0x0400)
  857.             regs.fpiar = nextilong();
  858.         }
  859.     } else if (extra & 0x2000) {
  860.         /* FMOVEM FPP->memory */
  861.         uae_u32 ad;
  862.         int incr = 0;
  863.  
  864.         if (get_fp_ad(opcode, &ad) == 0) {
  865.         m68k_setpc(m68k_getpc() - 4);
  866.         op_illg(opcode);
  867.         return;
  868.         }
  869.         if ((opcode & 0x38) == 0x20) {
  870.         if (extra & 0x1000)
  871.             incr += 4;
  872.         if (extra & 0x0800)
  873.             incr += 4;
  874.         if (extra & 0x0400)
  875.             incr += 4;
  876.         }
  877.         ad -= incr;
  878.         if (extra & 0x1000) {
  879.         put_long(ad, regs.fpcr);
  880.         ad += 4;
  881.         }
  882.         if (extra & 0x0800) {
  883.         put_long(ad, regs.fpsr);
  884.         ad += 4;
  885.         }
  886.         if (extra & 0x0400) {
  887.         put_long(ad, regs.fpiar);
  888.         ad += 4;
  889.         }
  890.         ad -= incr;
  891.         if ((opcode & 0x38) == 0x18)
  892.         m68k_areg(regs, opcode & 7) = ad;
  893.         if ((opcode & 0x38) == 0x20)
  894.         m68k_areg(regs, opcode & 7) = ad;
  895.     } else {
  896.         /* FMOVEM memory->FPP */
  897.         uae_u32 ad;
  898.  
  899.         if (get_fp_ad(opcode, &ad) == 0) {
  900.         m68k_setpc(m68k_getpc() - 4);
  901.         op_illg(opcode);
  902.         return;
  903.         }
  904.         ad = (opcode & 0x38) == 0x20 ? ad - 12 : ad;
  905.         if (extra & 0x1000) {
  906.         regs.fpcr = get_long(ad);
  907.         ad += 4;
  908.         }
  909.         if (extra & 0x0800) {
  910.         regs.fpsr = get_long(ad);
  911.         ad += 4;
  912.         }
  913.         if (extra & 0x0400) {
  914.         regs.fpiar = get_long(ad);
  915.         ad += 4;
  916.         }
  917.         if ((opcode & 0x38) == 0x18)
  918.         m68k_areg(regs, opcode & 7) = ad;
  919.         if ((opcode & 0x38) == 0x20)
  920.         m68k_areg(regs, opcode & 7) = ad - 12;
  921.     }
  922.     return;
  923.     case 6:
  924.     case 7:
  925.     {
  926.         uae_u32 ad, list = 0;
  927.         int incr = 0;
  928.         if (extra & 0x2000) {
  929.         /* FMOVEM FPP->memory */
  930.         if (get_fp_ad(opcode, &ad) == 0) {
  931.             m68k_setpc(m68k_getpc() - 4);
  932.             op_illg(opcode);
  933.             return;
  934.         }
  935.         switch ((extra >> 11) & 3) {
  936.         case 0:    /* static pred */
  937.             list = extra & 0xff;
  938.             incr = -1;
  939.             break;
  940.         case 1:    /* dynamic pred */
  941.             list = m68k_dreg(regs, (extra >> 4) & 3) & 0xff;
  942.             incr = -1;
  943.             break;
  944.         case 2:    /* static postinc */
  945.             list = extra & 0xff;
  946.             incr = 1;
  947.             break;
  948.         case 3:    /* dynamic postinc */
  949.             list = m68k_dreg(regs, (extra >> 4) & 3) & 0xff;
  950.             incr = 1;
  951.             break;
  952.         }
  953.         while (list) {
  954.             uae_u32 wrd1, wrd2, wrd3;
  955.             if (incr < 0) {
  956.             from_exten(
  957.                       regs.fp[fpp_movem_index2[list]],
  958.                       &wrd1, &wrd2, &wrd3);
  959.             ad -= 4;
  960.             put_long(ad, wrd3);
  961.             ad -= 4;
  962.             put_long(ad, wrd2);
  963.             ad -= 4;
  964.             put_long(ad, wrd1);
  965.             } else {
  966.             from_exten(
  967.                       regs.fp[fpp_movem_index1[list]],
  968.                       &wrd1, &wrd2, &wrd3);
  969.             put_long(ad, wrd1);
  970.             ad += 4;
  971.             put_long(ad, wrd2);
  972.             ad += 4;
  973.             put_long(ad, wrd3);
  974.             ad += 4;
  975.             }
  976.             list = fpp_movem_next[list];
  977.         }
  978.         if ((opcode & 0x38) == 0x18)
  979.             m68k_areg(regs, opcode & 7) = ad;
  980.         if ((opcode & 0x38) == 0x20)
  981.             m68k_areg(regs, opcode & 7) = ad;
  982.         } else {
  983.         /* FMOVEM memory->FPP */
  984.         if (get_fp_ad(opcode, &ad) == 0) {
  985.             m68k_setpc(m68k_getpc() - 4);
  986.             op_illg(opcode);
  987.             return;
  988.         }
  989.         switch ((extra >> 11) & 3) {
  990.         case 0:    /* static pred */
  991.             list = extra & 0xff;
  992.             incr = -1;
  993.             break;
  994.         case 1:    /* dynamic pred */
  995.             list = m68k_dreg(regs, (extra >> 4) & 3) & 0xff;
  996.             incr = -1;
  997.             break;
  998.         case 2:    /* static postinc */
  999.             list = extra & 0xff;
  1000.             incr = 1;
  1001.             break;
  1002.         case 3:    /* dynamic postinc */
  1003.             list = m68k_dreg(regs, (extra >> 4) & 3) & 0xff;
  1004.             incr = 1;
  1005.             break;
  1006.         }
  1007.         while (list) {
  1008.             uae_u32 wrd1, wrd2, wrd3;
  1009.             if (incr < 0) {
  1010.             ad -= 4;
  1011.             wrd3 = get_long(ad);
  1012.             ad -= 4;
  1013.             wrd2 = get_long(ad);
  1014.             ad -= 4;
  1015.             wrd1 = get_long(ad);
  1016.             regs.fp[fpp_movem_index2[list]] =
  1017.                 to_exten(wrd1, wrd2, wrd3);
  1018.             } else {
  1019.             wrd1 = get_long(ad);
  1020.             ad += 4;
  1021.             wrd2 = get_long(ad);
  1022.             ad += 4;
  1023.             wrd3 = get_long(ad);
  1024.             ad += 4;
  1025.             regs.fp[fpp_movem_index1[list]] =
  1026.                 to_exten(wrd1, wrd2, wrd3);
  1027.             }
  1028.             list = fpp_movem_next[list];
  1029.         }
  1030.         if ((opcode & 0x38) == 0x18)
  1031.             m68k_areg(regs, opcode & 7) = ad;
  1032.         if ((opcode & 0x38) == 0x20)
  1033.             m68k_areg(regs, opcode & 7) = ad;
  1034.         }
  1035.     }
  1036.     return;
  1037.     case 0:
  1038.     case 2:
  1039.     reg = (extra >> 7) & 7;
  1040.     if ((extra & 0xfc00) == 0x5c00) {
  1041.         switch (extra & 0x7f) {
  1042.         case 0x00:
  1043.         regs.fp[reg] = 4.0 * atan(1.0);
  1044.         break;
  1045.         case 0x0b:
  1046.         regs.fp[reg] = log10(2.0);
  1047.         break;
  1048.         case 0x0c:
  1049.         regs.fp[reg] = exp(1.0);
  1050.         break;
  1051.         case 0x0d:
  1052.         regs.fp[reg] = log(exp(1.0)) / log(2.0);
  1053.         break;
  1054.         case 0x0e:
  1055.         regs.fp[reg] = log(exp(1.0)) / log(10.0);
  1056.         break;
  1057.         case 0x0f:
  1058.         regs.fp[reg] = 0.0;
  1059.         break;
  1060.         case 0x30:
  1061.         regs.fp[reg] = log(2.0);
  1062.         break;
  1063.         case 0x31:
  1064.         regs.fp[reg] = log(10.0);
  1065.         break;
  1066.         case 0x32:
  1067.         regs.fp[reg] = 1.0e0;
  1068.         break;
  1069.         case 0x33:
  1070.         regs.fp[reg] = 1.0e1;
  1071.         break;
  1072.         case 0x34:
  1073.         regs.fp[reg] = 1.0e2;
  1074.         break;
  1075.         case 0x35:
  1076.         regs.fp[reg] = 1.0e4;
  1077.         break;
  1078.         case 0x36:
  1079.         regs.fp[reg] = 1.0e8;
  1080.         break;
  1081.         case 0x37:
  1082.         regs.fp[reg] = 1.0e16;
  1083.         break;
  1084.         case 0x38:
  1085.         regs.fp[reg] = 1.0e32;
  1086.         break;
  1087.         case 0x39:
  1088.         regs.fp[reg] = 1.0e64;
  1089.         break;
  1090.         case 0x3a:
  1091.         regs.fp[reg] = 1.0e128;
  1092.         break;
  1093.         case 0x3b:
  1094.         regs.fp[reg] = 1.0e256;
  1095.         break;
  1096. #if 0
  1097.         case 0x3c:
  1098.         regs.fp[reg] = 1.0e512;
  1099.         break;
  1100.         case 0x3d:
  1101.         regs.fp[reg] = 1.0e1024;
  1102.         break;
  1103.         case 0x3e:
  1104.         regs.fp[reg] = 1.0e2048;
  1105.         break;
  1106.         case 0x3f:
  1107.         regs.fp[reg] = 1.0e4096;
  1108.         break;
  1109. #endif
  1110.         default:
  1111.         m68k_setpc(m68k_getpc() - 4);
  1112.         op_illg(opcode);
  1113.         break;
  1114.         }
  1115.         return;
  1116.     }
  1117.     if (get_fp_value(opcode, extra, &src) == 0) {
  1118.         m68k_setpc(m68k_getpc() - 4);
  1119.         op_illg(opcode);
  1120.         return;
  1121.     }
  1122.     switch (extra & 0x7f) {
  1123.     case 0x00:        /* FMOVE */
  1124.         regs.fp[reg] = src;
  1125.         break;
  1126.     case 0x01:        /* FINT */
  1127.         regs.fp[reg] = (int) (src + 0.5);
  1128.         regs.fpsr = (regs.fp[reg] == 0 ? 0x4000000 : 0) |
  1129.         (regs.fp[reg] < 0 ? 0x8000000 : 0);
  1130.         break;
  1131.     case 0x02:        /* FSINH */
  1132.         regs.fp[reg] = sinh(src);
  1133.         regs.fpsr = (regs.fp[reg] == 0 ? 0x4000000 : 0) |
  1134.         (regs.fp[reg] < 0 ? 0x8000000 : 0);
  1135.         break;
  1136.     case 0x03:        /* FINTRZ */
  1137.         regs.fp[reg] = (int) src;
  1138.         regs.fpsr = (regs.fp[reg] == 0 ? 0x4000000 : 0) |
  1139.         (regs.fp[reg] < 0 ? 0x8000000 : 0);
  1140.         break;
  1141.     case 0x04:        /* FSQRT */
  1142.         regs.fp[reg] = sqrt(src);
  1143.         regs.fpsr = (regs.fp[reg] == 0 ? 0x4000000 : 0) |
  1144.         (regs.fp[reg] < 0 ? 0x8000000 : 0);
  1145.         break;
  1146.     case 0x06:        /* FLOGNP1 */
  1147.         regs.fp[reg] = log(src + 1.0);
  1148.         regs.fpsr = (regs.fp[reg] == 0 ? 0x4000000 : 0) |
  1149.         (regs.fp[reg] < 0 ? 0x8000000 : 0);
  1150.         break;
  1151.     case 0x08:        /* FETOXM1 */
  1152.         regs.fp[reg] = exp(src) - 1.0;
  1153.         regs.fpsr = (regs.fp[reg] == 0 ? 0x4000000 : 0) |
  1154.         (regs.fp[reg] < 0 ? 0x8000000 : 0);
  1155.         break;
  1156.     case 0x09:        /* FTANH */
  1157.         regs.fp[reg] = tanh(src);
  1158.         regs.fpsr = (regs.fp[reg] == 0 ? 0x4000000 : 0) |
  1159.         (regs.fp[reg] < 0 ? 0x8000000 : 0);
  1160.         break;
  1161.     case 0x0a:        /* FATAN */
  1162.         regs.fp[reg] = atan(src);
  1163.         regs.fpsr = (regs.fp[reg] == 0 ? 0x4000000 : 0) |
  1164.         (regs.fp[reg] < 0 ? 0x8000000 : 0);
  1165.         break;
  1166.     case 0x0c:        /* FASIN */
  1167.         regs.fp[reg] = asin(src);
  1168.         regs.fpsr = (regs.fp[reg] == 0 ? 0x4000000 : 0) |
  1169.         (regs.fp[reg] < 0 ? 0x8000000 : 0);
  1170.         break;
  1171.     case 0x0d:        /* FATANH */
  1172. #if 1                /* The BeBox doesn't have atanh, and it isn't in the HPUX libm either */
  1173.         regs.fp[reg] = log((1 + src) / (1 - src)) / 2;
  1174. #else
  1175.         regs.fp[reg] = atanh(src);
  1176. #endif
  1177.         regs.fpsr = (regs.fp[reg] == 0 ? 0x4000000 : 0) |
  1178.         (regs.fp[reg] < 0 ? 0x8000000 : 0);
  1179.         break;
  1180.     case 0x0e:        /* FSIN */
  1181.         regs.fp[reg] = sin(src);
  1182.         regs.fpsr = (regs.fp[reg] == 0 ? 0x4000000 : 0) |
  1183.         (regs.fp[reg] < 0 ? 0x8000000 : 0);
  1184.         break;
  1185.     case 0x0f:        /* FTAN */
  1186.         regs.fp[reg] = tan(src);
  1187.         regs.fpsr = (regs.fp[reg] == 0 ? 0x4000000 : 0) |
  1188.         (regs.fp[reg] < 0 ? 0x8000000 : 0);
  1189.         break;
  1190.     case 0x10:        /* FETOX */
  1191.         regs.fp[reg] = exp(src);
  1192.         regs.fpsr = (regs.fp[reg] == 0 ? 0x4000000 : 0) |
  1193.         (regs.fp[reg] < 0 ? 0x8000000 : 0);
  1194.         break;
  1195.     case 0x11:        /* FTWOTOX */
  1196.         regs.fp[reg] = pow(2.0, src);
  1197.         regs.fpsr = (regs.fp[reg] == 0 ? 0x4000000 : 0) |
  1198.         (regs.fp[reg] < 0 ? 0x8000000 : 0);
  1199.         break;
  1200.     case 0x12:        /* FTENTOX */
  1201.         regs.fp[reg] = pow(10.0, src);
  1202.         regs.fpsr = (regs.fp[reg] == 0 ? 0x4000000 : 0) |
  1203.         (regs.fp[reg] < 0 ? 0x8000000 : 0);
  1204.         break;
  1205.     case 0x14:        /* FLOGN */
  1206.         regs.fp[reg] = log(src);
  1207.         regs.fpsr = (regs.fp[reg] == 0 ? 0x4000000 : 0) |
  1208.         (regs.fp[reg] < 0 ? 0x8000000 : 0);
  1209.         break;
  1210.     case 0x15:        /* FLOG10 */
  1211.         regs.fp[reg] = log10(src);
  1212.         regs.fpsr = (regs.fp[reg] == 0 ? 0x4000000 : 0) |
  1213.         (regs.fp[reg] < 0 ? 0x8000000 : 0);
  1214.         break;
  1215.     case 0x16:        /* FLOG2 */
  1216.         regs.fp[reg] = log(src) / log(2.0);
  1217.         regs.fpsr = (regs.fp[reg] == 0 ? 0x4000000 : 0) |
  1218.         (regs.fp[reg] < 0 ? 0x8000000 : 0);
  1219.         break;
  1220.     case 0x18:        /* FABS */
  1221.         regs.fp[reg] = src < 0 ? -src : src;
  1222.         regs.fpsr = (regs.fp[reg] == 0 ? 0x4000000 : 0) |
  1223.         (regs.fp[reg] < 0 ? 0x8000000 : 0);
  1224.         break;
  1225.     case 0x19:        /* FCOSH */
  1226.         regs.fp[reg] = cosh(src);
  1227.         regs.fpsr = (regs.fp[reg] == 0 ? 0x4000000 : 0) |
  1228.         (regs.fp[reg] < 0 ? 0x8000000 : 0);
  1229.         break;
  1230.     case 0x1a:        /* FNEG */
  1231.         regs.fp[reg] = -src;
  1232.         regs.fpsr = (regs.fp[reg] == 0 ? 0x4000000 : 0) |
  1233.         (regs.fp[reg] < 0 ? 0x8000000 : 0);
  1234.         break;
  1235.     case 0x1c:        /* FACOS */
  1236.         regs.fp[reg] = acos(src);
  1237.         regs.fpsr = (regs.fp[reg] == 0 ? 0x4000000 : 0) |
  1238.         (regs.fp[reg] < 0 ? 0x8000000 : 0);
  1239.         break;
  1240.     case 0x1d:        /* FCOS */
  1241.         regs.fp[reg] = cos(src);
  1242.         regs.fpsr = (regs.fp[reg] == 0 ? 0x4000000 : 0) |
  1243.         (regs.fp[reg] < 0 ? 0x8000000 : 0);
  1244.         break;
  1245.     case 0x1e:        /* FGETEXP */
  1246.         {
  1247.         int expon;
  1248.         frexp(src, &expon);
  1249.         regs.fp[reg] = (double) (expon - 1);
  1250.         regs.fpsr = (regs.fp[reg] == 0 ? 0x4000000 : 0) |
  1251.             (regs.fp[reg] < 0 ? 0x8000000 : 0);
  1252.         }
  1253.         break;
  1254.     case 0x1f:        /* FGETMAN */
  1255.         {
  1256.         int expon;
  1257.         regs.fp[reg] = frexp(src, &expon) * 2.0;
  1258.         regs.fpsr = (regs.fp[reg] == 0 ? 0x4000000 : 0) |
  1259.             (regs.fp[reg] < 0 ? 0x8000000 : 0);
  1260.         }
  1261.         break;
  1262.     case 0x20:        /* FDIV */
  1263.         regs.fp[reg] /= src;
  1264.         regs.fpsr = (regs.fp[reg] == 0 ? 0x4000000 : 0) |
  1265.         (regs.fp[reg] < 0 ? 0x8000000 : 0);
  1266.         break;
  1267.     case 0x21:        /* FMOD */
  1268.         regs.fp[reg] = regs.fp[reg] -
  1269.         (double) ((int) (regs.fp[reg] / src)) * src;
  1270.         regs.fpsr = (regs.fp[reg] == 0 ? 0x4000000 : 0) |
  1271.         (regs.fp[reg] < 0 ? 0x8000000 : 0);
  1272.         break;
  1273.     case 0x22:        /* FADD */
  1274.         regs.fp[reg] += src;
  1275.         regs.fpsr = (regs.fp[reg] == 0 ? 0x4000000 : 0) |
  1276.         (regs.fp[reg] < 0 ? 0x8000000 : 0);
  1277.         break;
  1278.     case 0x23:        /* FMUL */
  1279.         regs.fp[reg] *= src;
  1280.         regs.fpsr = (regs.fp[reg] == 0 ? 0x4000000 : 0) |
  1281.         (regs.fp[reg] < 0 ? 0x8000000 : 0);
  1282.         break;
  1283.     case 0x24:        /* FSGLDIV */
  1284.         regs.fp[reg] /= src;
  1285.         regs.fpsr = (regs.fp[reg] == 0 ? 0x4000000 : 0) |
  1286.         (regs.fp[reg] < 0 ? 0x8000000 : 0);
  1287.         break;
  1288.     case 0x25:        /* FREM */
  1289.         regs.fp[reg] = regs.fp[reg] -
  1290.         (double) ((int) (regs.fp[reg] / src + 0.5)) * src;
  1291.         regs.fpsr = (regs.fp[reg] == 0 ? 0x4000000 : 0) |
  1292.         (regs.fp[reg] < 0 ? 0x8000000 : 0);
  1293.         break;
  1294.     case 0x26:        /* FSCALE */
  1295.         regs.fp[reg] *= exp(log(2.0) * src);
  1296.         regs.fpsr = (regs.fp[reg] == 0 ? 0x4000000 : 0) |
  1297.         (regs.fp[reg] < 0 ? 0x8000000 : 0);
  1298.         break;
  1299.     case 0x27:        /* FSGLMUL */
  1300.         regs.fp[reg] *= src;
  1301.         regs.fpsr = (regs.fp[reg] == 0 ? 0x4000000 : 0) |
  1302.         (regs.fp[reg] < 0 ? 0x8000000 : 0);
  1303.         break;
  1304.     case 0x28:        /* FSUB */
  1305.         regs.fp[reg] -= src;
  1306.         regs.fpsr = (regs.fp[reg] == 0 ? 0x4000000 : 0) |
  1307.         (regs.fp[reg] < 0 ? 0x8000000 : 0);
  1308.         break;
  1309.     case 0x30:        /* FSINCOS */
  1310.     case 0x31:
  1311.     case 0x32:
  1312.     case 0x33:
  1313.     case 0x34:
  1314.     case 0x35:
  1315.     case 0x36:
  1316.     case 0x37:
  1317.         regs.fp[reg] = sin(src);
  1318.         regs.fp[extra & 7] = cos(src);
  1319.         regs.fpsr = (regs.fp[reg] == 0 ? 0x4000000 : 0) |
  1320.         (regs.fp[reg] < 0 ? 0x8000000 : 0);
  1321.         break;
  1322.     case 0x38:        /* FCMP */
  1323.         {
  1324.         double tmp = regs.fp[reg] - src;
  1325.         regs.fpsr = (tmp == 0 ? 0x4000000 : 0) |
  1326.             (tmp < 0 ? 0x8000000 : 0);
  1327.         }
  1328.         break;
  1329.     case 0x3a:        /* FTST */
  1330.         regs.fpsr = (src == 0 ? 0x4000000 : 0) |
  1331.         (src < 0 ? 0x8000000 : 0);
  1332.         break;
  1333.     default:
  1334.         m68k_setpc(m68k_getpc() - 4);
  1335.         op_illg(opcode);
  1336.         break;
  1337.     }
  1338.     return;
  1339.     }
  1340.     m68k_setpc(m68k_getpc() - 4);
  1341.     op_illg(opcode);
  1342. }
  1343.  
  1344. #endif
  1345.